# Calorie counting web application
# Authored by Lynn Garrett, Jessica Nixon, and Kyle Solan

#IMPORTING---------------------------------------------------

from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp.util import run_wsgi_app
import datetime
import uuid

#USER AUTHENTICATION-----------------------------------------

class MyUser(object):
    def __init__(self, name): self.name = name
    def nickname(self): return self.name

def get_user(page):
    """return a user or None (and do a redirect)"""
    user = users.User('kyle.solan@gmail.com')
    #user = users.get_current_user() #enable for web use
    if user: return user
    if not user:
        page.redirect(users.create_login_url(page.request.uri))
        return None

#DATASTORE OBJECTS-----------------------------------------------

class Item(db.Model):
    """ an item contains the name of the item and its calorie count"""
    name = db.StringProperty()
    calories = db.IntegerProperty()
    item_id = db.StringProperty()
    
def add_item(name, calories):
    """ adds an item with the give name and calorie count and returns the item's key in the database"""
    item = Item()
    item.name = name
    item.calories = calories
    item.item_id = uuid.uuid1().hex
    item.put() #stores the item in the database
    return item.item_id #returns the unique ID that needs to go into the Day object

class Day(db.Model):
    """a day has a user, date, and a list of item ids"""
    user = db.UserProperty()
    date = db.DateProperty(auto_now_add=True)
    total_calories = db.IntegerProperty()
    list_of_items = db.ListProperty(str)

def get_all_items():
    query = db.GqlQuery("SELECT * FROM Item")
    return query.fetch(100)

def convert_to_datetime(date_string):
    date_string = date_string.split("/")
    user_month = int(date_string[0])
    user_day = int(date_string[1])
    user_year = int(date_string[2])
    user_date = datetime.date(user_year, user_month, user_day)
    return user_date

def convert_from_datetime(date_obj):
    year = str(date_obj.year)
    month = str(date_obj.month)
    day = str(date_obj.day)
    return "/".join([month, day, year])
    
def add_day(user, calories):
    day = Day()
    day.user = user
    day.total_calories = calories
    day.list_of_items = list()
    day.put() # stores the day in the database
    
def add_item_to_day(day, item_id):
    """ appends the item id to the list of item ids associate with the given day"""
    get_day(day).list_of_items.append(str(item_id))
    get_day(day).put()

def get_day(day):
    return day[0]

def get_all_days():
    q = db.GqlQuery("SELECT * from Day")
    return q.fetch(100)
    
def get_list_of_items(day):
    """returns a list of items associated with the given day"""
    item_ids = get_day(day).list_of_items
    item_list = []
    for item_id in item_ids:
        query = db.GqlQuery("SELECT * FROM Item WHERE item_id = :1", item_id)
        item = query[0]
        item_list.append(item)
    return item_list
def convert_datetime_today(date_string):
    date_list = date_string.split("-")
    return str(int(date_list[1])) + "/" + date_list[2] + "/" + date_list[0]
    

def get_calories_remaining(day):
    items = get_list_of_items(day)
    total_cals = 0
    if not items:
        return get_day(day).total_calories
    else:
        for item in items:
            total_cals += item.calories
        return get_day(day).total_calories - total_cals
    
def get_toolbar_calories(day):
    """ returns a tuple containing the (calories remaining, total calories) for the given day, returns 0/0 if day is None"""
    if not day:
        return ("", "")
    else:
        return(str(get_calories_remaining(day)), str(get_day(day).total_calories))
    

#PAGES/CONTENT-----------------------------------------------

def display_day(day):
    """ displays the list of items and their calorie values for a given day. Returns an html string"""
    html_string = ""
    items = get_list_of_items(day)
    if not items:
        return "<p> Your day has no items in it! </p>"
    else:
        for item in items:
            html_string += """
    <tr> 
        <td><font face="Century Gothic"><font color="wheat"font/>%s</td> 
        <td><font face="Century Gothic"><font color="wheat"font/>%d</td> 
    </tr> """ % (item.name, item.calories)
        return html_string

# ------------------------------------------------------------------------        

class HomePage(webapp.RequestHandler):
    def get(self):
        user = get_user(self)
        query = db.GqlQuery("SELECT * FROM Day WHERE user = :1 ORDER BY date LIMIT 1", user)
        day = query.fetch(1)
        cal_used, cal_total = get_toolbar_calories(day)
        if not user: return
        self.response.out.write("""
<html>
<head>
<link type="text/css" rel="stylesheet" href="/static/style.css" />
<title>CalCount</title>
</head>
<body>
<div class="topbar">
    <a href="/"><img src="/static/header.png" style="width: 119px; height: 53px;"/></a>
    <div style="float:right">
        <b>Welcome, %s</b>
        &nbsp; Calories for today:
        <input type="text" style="height:20px;font-size:12px" size=10 name="day_cals" value="%s/%s"/>
    </div>
</div>
<h1 style="text-align:center"><img src= "/static/header.png" / ></h1>
<p>Welcome to CalCount, the easy way of keeping track of your daily intake of
calories to ensure a healthier lifestyle.
<br />
<br />
You can set daily targets for yourself and watch your calorie intake over time.</p>
</div>
<br />
<form align="center">
<input value="Let's get started!" type="button" class="start" onclick="window.location.href='/main'" />
</form>

</body>
</html>
""" % (user, cal_used, cal_total))

# --------------------------------------------------------------------------

class MainPage(webapp.RequestHandler):
    def get(self):
        user = get_user(self)
        query = db.GqlQuery("SELECT * FROM Day WHERE user = :1 ORDER BY date LIMIT 1", user)
        day = query.fetch(1)
        cal_used, cal_total = get_toolbar_calories(day)
        if not user:
            return
        self.response.out.write("""
<html>
<head>
    <script type="text/javascript" src="/static/script.js"></script>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <title>CalCount</title>
</head>
<body>
<div class="topbar">
    <a href="/"><img src="/static/header.png" style="width: 119px; height: 53px;"/></a>
    <div style="float:right">
        <b>Welcome, %s</b>
        &nbsp; Calories for today:
        <input type="text" style="height:20px;font-size:12px" size=10 name="day_cals" value="%s/%s"/>
    </div>
</div>
<div style="clear: both;"></div>
<h1><img src="/static/header.png" /></h1>
        <form action="handle" name="data" method=post>
        <h1>Today's Date:
        %s</h1>
        <div id="newday" style="display:none">
        <h3 style="text-align:center">Today is a new day!<br />
        Please enter your target calories for the day:
        <input type="text" name="target" /><br />
        <input id="initdatebtn" type="button" value="Submit" onclick="UnhideTable();" />
        </h3>
        </div>
        <div id="CalorieTable" align="center">
        <h2>Enter what you've eaten!</h2>
        <table id="Calories" border="5" bordercolor="#wheat" bgcolor="yellowgreen" cellspacing="2" cellpadding="3">
            <tr>
                <td>Item Name:</td>
                <td><input type="text" name="item_name0" id="item_name0" /></td>
                <td>Calories:</td>
                <td><input type="text" name="calories0" /></td>
            </tr>
        </table>
        <center><a href="javascript:addRowToTable()" class="link">Another row</a></center>
        <input type="hidden" id="endofrow" name="endofrow" value="0" />
        <br />
        <br />
        <center><input type="submit" value="Submit Data" /></center>
        </div>
    </form>
</body>
</html>
""" % (user, cal_used, cal_total, convert_from_datetime(datetime.date.today())))

        if not day or convert_from_datetime(get_day(day).date) != convert_from_datetime(datetime.date.today()):
            self.response.out.write("""
<script type="text/javascript">
document.getElementById("newday").style.display = "inline";
document.getElementById("CalorieTable").style.display = "none";
</script>
""")


# --------------------------------------------------------------------------    

class DisplayDayPage(webapp.RequestHandler):
    def get(self):
        user = get_user(self)
        if not user:
            return
        query = db.GqlQuery("SELECT * FROM Day WHERE user = :1 ORDER BY date LIMIT 1", user)
        day = query.fetch(1)
        cal_used, cal_total = get_toolbar_calories(day)
        self.response.out.write("""
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<script type="text/javascript" src="/static/calendar_us.js"></script>
<link type="text/css" rel="stylesheet" href="/static/style.css" />
<link type="text/css" rel="stylesheet" href="/static/calendar.css" />
</head>
<body>
<div class="topbar">
    <a href="/"><img src="/static/header.png" style="width: 119px; height: 53px;"/></a>
    <div style="float:right">
        <b>Welcome, %s</b>
        &nbsp; Calories for today:
        <input type="text" style="height:20px;font-size:12px" size=10 name="day_cals" value="%s/%s"/>
    </div>
</div>
<h1><img src= "/static/header.png"</h1>
<h3 style="text-align:center">You have %d calories remaining for today</h3> 
 
<table border="5" align="center" bordercolor="#wheat" bgcolor="yellowgreen" width="500" 

cellspacing="2" cellpadding="3">
<tr>
    <td><font face="Century Gothic"><font color="wheat"> Date: %s </font></td>
    <td> </td>
</tr>
<tr> 
    <td><font face="Century Gothic"><font color="wheat">Food Item</font></td> 
    <td><font face="Century Gothic"><font color="wheat">Calories</font></td> 
</tr> """ % (user, cal_used, cal_total, get_calories_remaining(day), convert_from_datetime(get_day(day).date)) )
        self.response.out.write(display_day(day))
        self.response.out.write("""
</table>
<center><form name="testform" method=post action="handledate"> 
	<!-- calendar attaches to existing form element --> 
	<input type="text" size=10 name="calendar" /> 
	<script language="javascript"> 
	new tcal ({
		// form name
		'formname': 'testform',
		// input name
		'controlname': 'calendar'
	});
	</script>
	<input type="submit" value="View a different date" />
</form></center>
<br />
<br />
<a href="/main"> Add more items. </a>
</body>
</html> """)

# ------------------------------------

class HandleDateRequest(webapp.RequestHandler):
    """ takes what the user gives in the javascript calendar and returns the day
        or an Error if the day doesn't exist"""
    def post(self):
        user = get_user(self)
        if not user:
            return
        user_date = convert_to_datetime(self.request.get("calendar"))
        query = db.GqlQuery("SELECT * FROM Day WHERE user = :1 and date= :2",
                            user, user_date)
        day = query.fetch(1)
        cal_used, cal_total = get_toolbar_calories(day)
        if not day:
            self.response.out.write("""
<html>
<head>
<link type="text/css" rel="stylesheet" href="/static/style.css" />
<title>CalCount</title>
</head>
<body>
<div class="topbar">
    <a href="/"><img src="/static/header.png" style="width: 119px; height: 53px;"/></a>
    <div style="float:right">
        <b>Welcome, %s</b>
        &nbsp; Calories for today:
        <input type="text" style="height:20px;font-size:12px" size=10 name="day_cals" value="%s/%s"/>
    </div>
</div>
<h1><img src="/static/header.png" /></h1>
<p>
Error: this day doesn't exist!
<br />
<a href = "/main">Return to the Main Page </a>
<br />

</p> """ % (user, cal_used, cal_total))
        else:
            self.response.out.write("""
    <html>
    <head>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <title>CalCount</title>
    </head>
    <body>
    <div class="topbar">
    <a href="/"><img src="/static/header.png" style="width: 119px; height: 53px;"/></a>
    <div style="float:right">
        <b>Welcome, %s</b>
        &nbsp; Calories for today:
        <input type="text" style="height:20px;font-size:12px" size=10 name="day_cals" value="%s/%s"/>
        </div>
    </div>
    <p>
    Here is your date:
    </p> 
    <table border="5" align="center" bordercolor="#wheat" bgcolor="yellowgreen" width="500" 

    cellspacing="2" cellpadding="3">
    <tr> 
        <td><font face="Century Gothic"><font color="wheat">Food Item</font></td> 
        <td><font face="Century Gothic"><font color="wheat">Calories</font></td> 
    </tr> """ % (user, cal_used, cal_total))
            self.response.out.write(display_day(day))
            self.response.out.write("""
    </body>
    </html> """)


        
# --------------------------------------------------------------------------

class HandleFormPage(webapp.RequestHandler):
    def post(self):
        user = get_user(self)
        query = db.GqlQuery("SELECT * FROM Day ORDER BY date LIMIT 1")
        day = query.fetch(1)
        cal_used, cal_total = get_toolbar_calories(day)

        i = 0
        if not user:
            return
        if (not day or convert_from_datetime(get_day(day).date) !=
             convert_from_datetime(datetime.date.today())):
            calories = int(self.request.get("target"))
            add_day(user, calories) 
            query = db.GqlQuery("SELECT * FROM Day ORDER BY date LIMIT 1")
            day = query.fetch(1)
        while i <= (int(self.request.get("endofrow"))):           
            item_name = self.request.get("item_name" + str(i))
            calstring = self.request.get("calories" + str(i))
            cal = int(calstring)
            item_id = add_item(item_name, cal)
            add_item_to_day(day, item_id)
            i += 1
        self.response.out.write("""
    <html>
    <head>
    <link type="text/css" rel="stylesheet" href="/static/style.css" />
    <title>CalCount</title>
    </head>
    <body>
    <div class="topbar">
    <a href="/"><img src="/static/header.png" style="width: 119px; height: 53px;"/></a>
    <div style="float:right">
        <b>Welcome, %s</b>
        &nbsp; Calories for today:
        <input type="text" style="height:20px;font-size:12px" size=10 name="day_cals" value="%s/%s"/>
        </div>
    </div>
    <h1><img src="/static/header.png" /></h1>
    <p> Congratulations! Your request was handled successfully.
    <br />
    <form action="display" method=get>
    <center><input type=submit value="View your day so far" /></center>
    </form>
    <br />
    <center><a href="/main"> Return home? </a></center>
    </p>
     </body>
    </html>""" % (user, cal_used, cal_total))

        


# INITIALIZATION----------------------------------------------

application = webapp.WSGIApplication(
                                     [('/main', MainPage),
                                      ('/', HomePage),
                                      ('/handle', HandleFormPage),
                                      ('/handledate', HandleDateRequest),
                                      ('/display', DisplayDayPage)
                                     ],
                                     debug = True)
    
def main():
    run_wsgi_app(application)
    
if __name__ == '__main__':
    main()
